package com.i2silly.wxbot.quartz.impl;

import com.i2silly.wxbot.quartz.QuartzJobService;
import com.i2silly.wxbot.quartz.ScheduleJob;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @description：Quartz任务管理服务类
 * @author: lxinjie@linewell.com
 * @since: 2017年3月6日 上午11:53:34
 */
@Service
public class QuartzJobServiceImpl implements QuartzJobService {
    
    private static final Logger log = LoggerFactory.getLogger(QuartzJobServiceImpl.class);
    
    private final static String JOB_GROUP_SUFFIX = "_JOB";  
    private final static String TRIGGER_GROUP_SUFFIX = "_TRIGGER"; 
    
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Override
    public void addJob(String jobName, Class<? extends Job> jobClass, String cron) {
        addJob(jobName, jobName.toUpperCase()+JOB_GROUP_SUFFIX, jobName, jobName.toUpperCase()+TRIGGER_GROUP_SUFFIX, jobClass, cron);
    }

    @Override
    public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<? extends Job> jobClass, String cron) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();
            scheduler.scheduleJob(jobDetail, trigger); 
            if (!scheduler.isShutdown()) {  
                scheduler.start();  
            }  
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        } 
    }

    @Override
    public void modifyJobCron(String jobName, String cron) {
        modifyJobCron(jobName, jobName.toUpperCase()+JOB_GROUP_SUFFIX, jobName, jobName.toUpperCase()+TRIGGER_GROUP_SUFFIX, cron);
    }

    @Override
    public void modifyJobCron(String jobName, 
            String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {  
                return;  
            }
            String oldCron = trigger.getCronExpression();
            if (!oldCron.equalsIgnoreCase(cron)) { 
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                trigger = (CronTrigger) triggerBuilder.build();
                scheduler.rescheduleJob(triggerKey, trigger);
            }
        }catch(SchedulerException e){
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void removeJob(String jobName) {
        removeJob(jobName, jobName.toUpperCase()+JOB_GROUP_SUFFIX, jobName, jobName.toUpperCase()+TRIGGER_GROUP_SUFFIX);
    }

    @Override
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
        } catch (SchedulerException e) {  
            log.error(e.getMessage(), e);
        } 
    }

    @Override
    public void startJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.start();
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void shutdownJobs() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            if (!scheduler.isShutdown()) {  
                scheduler.shutdown();
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public List<ScheduleJob> intendJob() {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    ScheduleJob job = new ScheduleJob();
                    job.setName(jobKey.getName());
                    job.setGroup(jobKey.getGroup());
                    job.setDescription("触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setStatus(triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.setCronExpression(cronExpression);
                    }
                    jobList.add(job);
                }
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
        return jobList;
    }

    @Override
    public void pauseJob(String jobName) {
        pauseJob(jobName, jobName.toUpperCase()+JOB_GROUP_SUFFIX, jobName, jobName.toUpperCase()+TRIGGER_GROUP_SUFFIX);
    }

    @Override
    public void pauseJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
        } catch (SchedulerException e) {  
            log.error(e.getMessage(), e);
        } 
    }

    @Override
    public List<ScheduleJob> runningJob() {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        try {
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            for (JobExecutionContext executingJob : executingJobs) {
                ScheduleJob job = new ScheduleJob();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                job.setName(jobKey.getName());
                job.setGroup(jobKey.getGroup());
                job.setDescription("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
        return jobList;
    }

    @Override
    public void resumeJob(String jobName) {
        resumeJob(jobName, jobName.toUpperCase()+JOB_GROUP_SUFFIX, jobName, jobName.toUpperCase()+TRIGGER_GROUP_SUFFIX);
    }

    @Override
    public void resumeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
        } catch (SchedulerException e) {  
            log.error(e.getMessage(), e);
        } 
    }
    
    
}
